﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MP3SharpFix
{

    public class Mp3IDFrame
    {
        public int version;
        public int framesize;
        public byte[] datawithhead;

        public static bool IsIDFrame(int headerInt)
        {
            if ((headerInt & 0xFFFFFF00U) == 0x49443300)//ID version1
            {
                byte flagsMask = (byte)(headerInt & 0xFF);
                if (flagsMask == 3 || flagsMask == 4)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if ((headerInt & 0xFFFFFF00U) == 0x54414700)
            {
                return true;
            }
            return false;
        }
        public static bool TryRead(System.IO.Stream stream, int headerInt, out Mp3IDFrame idframe)
        {
            if ((headerInt & 0xFFFFFF00U) == 0x49443300)//ID version1
            {
                byte flagsMask = (byte)(headerInt & 0xFF);
                if (flagsMask == 3 || flagsMask == 4)
                {

                    byte[] buf = new byte[6];
                    int bufl = stream.Read(buf, 0, 6);
                    if (bufl < 6)
                    {
                        idframe = null;
                        return false;
                    }
                    var fsize = (buf[2] << 21)
                 | (buf[3] << 14)
                 | (buf[4] << 7)
                 | (buf[5]);
                    // finally, check to make sure that all the right bits are cleared
                    if (!(((buf[1] & flagsMask) | (buf[2] & 0x80) | (buf[3] & 0x80) | (buf[4] & 0x80) | (buf[5] & 0x80)) != 0 || buf[0] == 0xFF))
                    {
                        idframe = new Mp3IDFrame();
                        idframe.version = 1;
                        idframe.framesize = fsize;
                        idframe.datawithhead = new byte[fsize + 10];
                        idframe.datawithhead[0] = (byte)((headerInt >> 24) & 0xFF);
                        idframe.datawithhead[1] = (byte)((headerInt >> 16) & 0xFF);
                        idframe.datawithhead[2] = (byte)((headerInt >> 8) & 0xFF);
                        idframe.datawithhead[3] = (byte)((headerInt) & 0xFF);
                        for (var i = 0; i < 6; i++)
                        {
                            idframe.datawithhead[i + 4] = buf[i];
                        }
                        stream.Read(idframe.datawithhead, 10, fsize);
                        return true;
                        //return size + 10;   // don't forget the sync, flag & size bytes!
                    }

                }
                idframe = null;
                return false;
            }
            else if ((headerInt & 0xFFFFFF00U) == 0x54414700)
            {
                idframe = new Mp3IDFrame();
                if ((headerInt & 0xFF) == 0x2B)
                {
                    //ID version1
                    idframe.version = 1;
                    idframe.framesize = 227 + 128 - 4;

                }
                else
                {
                    //ID version0
                    idframe.version = 2;
                    idframe.framesize = 128 - 4;
                }

                idframe.datawithhead = new byte[idframe.framesize + 4];
                idframe.datawithhead[0] = (byte)((headerInt >> 24) & 0xFF);
                idframe.datawithhead[1] = (byte)((headerInt >> 16) & 0xFF);
                idframe.datawithhead[2] = (byte)((headerInt >> 8) & 0xFF);
                idframe.datawithhead[3] = (byte)((headerInt) & 0xFF);
                stream.Read(idframe.datawithhead, 4, idframe.framesize);

                return true;

            }
            else
            {
                idframe = null;
                return false;
            }
        }
    }
    public class Mp3RiffFrame
    {
        public byte[] datawithhead;

        public static bool TryRead(System.IO.Stream stream, int headerInt, out Mp3RiffFrame riffFrame)
        {
            int rlen = 0;
            if (headerInt == 0x52494646U)
            {
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    var buf = new byte[4];
                    buf[0] = (byte)((headerInt >> 24) & 0xFF);
                    buf[1] = (byte)((headerInt >> 16) & 0xFF);
                    buf[2] = (byte)((headerInt >> 8) & 0xFF);
                    buf[3] = (byte)((headerInt) & 0xFF);
                    ms.Write(buf, 0, 4);



                    rlen = stream.Read(buf, 0, 4);//这4个字节不要
                    ms.Write(buf, 0, 4);

                    // we expect this to be the "WAVE" chunk
                    rlen = stream.Read(buf, 0, 4);
                    if (rlen < 4 || buf[0] != 'W' || buf[1] != 'A' || buf[2] != 'V' || buf[3] != 'E')
                    {
                        riffFrame = null;
                        return false;
                    }
                    ms.Write(buf, 0, 4);

                    // now the "fmt " chunk
                    rlen = stream.Read(buf, 0, 4);//这4个字节不要
                    if (rlen < 4 || buf[0] != 'f' || buf[1] != 'm' || buf[2] != 't' || buf[3] != ' ')
                    {
                        riffFrame = null;
                        return false;
                    }
                    ms.Write(buf, 0, 4);

                    // we've found the fmt chunk, so look for the data chunk
                    while (true)
                    {
                        // read the length and seek forward
                        rlen = stream.Read(buf, 0, 4);
                        if (rlen < 4)
                        {
                            riffFrame = null;
                            return false;
                        }
                        ms.Write(buf, 0, 4);

                        var size = BitConverter.ToInt32(buf, 0);
                        var data = new byte[size];
                        stream.Read(data, 0, size);
                        ms.Write(data, 0, size);

                        // get the chunk ID
                        rlen = stream.Read(buf, 0, 4);
                        if (rlen < 4)
                        {
                            riffFrame = null;
                            return false;
                        }
                        ms.Write(buf, 0, 4);

                        // if it's not the data chunk, try again
                        if (buf[0] == 'd' && buf[1] == 'a' && buf[2] == 't' && buf[3] == 'a')
                            break;
                    }
                    riffFrame = new Mp3RiffFrame();
                    riffFrame.datawithhead = ms.ToArray();
                    return true;
                }
            }
            else
            {
                riffFrame = null;
                return false;
            }
        }
    }
    public class VBRInfo
    {
        public int SampleCount;
        public int SampleRate;
        public int Channels;
        public int VBRFrames;
        public int VBRBytes;
        public int VBRQuality;
        public int VBRDelay;
    }
}
